﻿//-----------------------------------------------------------------------
// <copyright file="Group.cs" company="Noboru Project">
//      Copyright (c) Noboru Project. All rights reserved.
//
//      This source code is subject to terms and conditions of the New BSD License (BSD).
//      A copy of the license can be found in the License.html file at the root of this 
//      distribution. If you can not locate the New BSD License (BSD), please send an 
//      email to noboru_adm@live.com.
//      By using this source code in any fashion, you are agreeing to be bound by
//      the terms of the New BSD License (BSD) for Noboru.
//
//      You must not remove this notice, or any other, from this software.
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Noboru.Windows.Controls
{
    /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.Class"]/*' />
    [TemplatePart(Name = "BackgroundPart", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "TitlePart", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "LauncherPart", Type = typeof(FrameworkElement))]
    [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "LauncherMouseOver", GroupName = "LauncherStates")]
    [TemplateVisualState(Name = "LauncherNormal", GroupName = "LauncherStates")]
    public class Group : ContentControl
    {
        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.TitleProperty"]/*'/>
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(Group), null);

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.LauncherVisibilityProperty"]/*'/>
        public static readonly DependencyProperty LauncherVisibilityProperty = DependencyProperty.Register("LauncherVisibility", typeof(Visibility), typeof(Group), new PropertyMetadata(Visibility.Visible, Group.LauncherVisibilityPropertyChangedCallback));

        private bool _isMouseOver;
        private bool _isLauncherMouseOver;
        private FrameworkElement _launcherPart;

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.Constructor"]/*'/>
        public Group()
        {
            this.DefaultStyleKey = typeof(Group);
            this.MouseEnter += new MouseEventHandler(this.Group_MouseEnter);
            this.MouseLeave += new MouseEventHandler(this.Group_MouseLeave);

            this.ApplyCommonState(false);
        }

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.LauncherClick"]/*' />
        public event RoutedEventHandler LauncherClick;

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.Title"]/*'/>
        public string Title
        {
            get
            {
                return (string)this.GetValue(TitleProperty);
            }

            set
            {
                this.SetValue(TitleProperty, value);
            }
        }

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.LauncherVisibility"]/*'/>
        public Visibility LauncherVisibility
        {
            get
            {
                return (Visibility)this.GetValue(LauncherVisibilityProperty);
            }

            set
            {
                this.SetValue(LauncherVisibilityProperty, value);
            }
        }

        private FrameworkElement LauncherPart
        {
            get
            {
                return this._launcherPart;
            }

            set
            {
                FrameworkElement oldPart = this._launcherPart;
                if (oldPart != null)
                {
                    oldPart.MouseLeftButtonDown -= new MouseButtonEventHandler(this.LauncherPart_MouseLeftButtonDown);
                    oldPart.MouseEnter -= new MouseEventHandler(this.LauncherPart_MouseEnter);
                    oldPart.MouseLeave -= new MouseEventHandler(this.LauncherPart_MouseLeave);
                }

                this._launcherPart = value;

                if (this._launcherPart != null)
                {
                    this._launcherPart.MouseLeftButtonDown += new MouseButtonEventHandler(this.LauncherPart_MouseLeftButtonDown);
                    this._launcherPart.MouseEnter += new MouseEventHandler(this.LauncherPart_MouseEnter);
                    this._launcherPart.MouseLeave += new MouseEventHandler(this.LauncherPart_MouseLeave);
                }
            }
        }

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.OnApplyTemplate"]/*'/>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.LauncherPart = (FrameworkElement)GetTemplateChild("LauncherPart");
        }

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.OnLauncherVisibilityChanged"]/*'/>
        protected virtual void OnLauncherVisibilityChanged(DependencyPropertyChangedEventArgs e)
        {
            if (this._launcherPart != null)
            {
                this._launcherPart.Visibility = this.LauncherVisibility;
            }
        }

        /// <include file='Documentation\GroupDocumentation.uex' path='Members/Member[@for="Group.OnLauncherClicked"]/*'/>
        protected virtual void OnLauncherClicked(RoutedEventArgs e)
        {
            if (this.LauncherClick != null)
            {
                this.LauncherClick(this, e);
            }
        }

        private static void LauncherVisibilityPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((Group)sender).OnLauncherVisibilityChanged(e);
        }

        private void ApplyLauncherState(bool useTransitions)
        {
            if (this.IsEnabled)
            {
                if (this._isLauncherMouseOver)
                {
                    VisualStateManager.GoToState(this, "LauncherMouseOver", useTransitions);
                }
                else
                {
                    VisualStateManager.GoToState(this, "LauncherNormal", useTransitions);
                }
            }
        }

        private void ApplyCommonState(bool useTransitions)
        {
            if (this.IsEnabled)
            {
                if (this._isMouseOver)
                {
                    VisualStateManager.GoToState(this, "MouseOver", useTransitions);
                }
                else
                {
                    VisualStateManager.GoToState(this, "Normal", useTransitions);
                }
            }
            else
            {
                VisualStateManager.GoToState(this, "Disabled", useTransitions);
            }
        }

        private void LauncherPart_MouseLeave(object sender, MouseEventArgs e)
        {
            this._isLauncherMouseOver = false;

            this.ApplyLauncherState(true);
        }

        private void LauncherPart_MouseEnter(object sender, MouseEventArgs e)
        {
            this._isLauncherMouseOver = true;

            this.ApplyLauncherState(true);
        }

        private void LauncherPart_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.OnLauncherClicked(new RoutedEventArgs());
        }

        private void Group_MouseEnter(object sender, MouseEventArgs e)
        {
            this._isMouseOver = true;

            this.ApplyCommonState(true);
        }

        private void Group_MouseLeave(object sender, MouseEventArgs e)
        {
            this._isMouseOver = false;

            this.ApplyCommonState(true);
        }
    }
}
